/*                                    _
 *   ___ _ __ ___ _ __ ___   ___   __| |
 *  / __| '__/ __| '_ ` _ \ / _ \ / _` |
 *  \__ \ |  \__ \ | | | | | (_) | (_| |
 *  |___/_|  |___/_| |_| |_|\___/ \__,_|                            
 *
 *     _  _  _ _ |_ .|_ ._|_  |_  _  _ _ _ _
 * |_|| ||_)| (_)| |||_)| |   |_)(_)_\_\(/_\                
 *       |    _ _  _  _|   | _ 
 *           | | |(_)(_||_||(/_
 *
 ******************************************
 ******************************************
 ******************************************
 * . _ _  _ | _  _ _  _  _ _|_ _ _|_. _  _ 
 * || | ||_)|(/_| | |(/_| | | (_| | |(_)| |
 *       |                                 
 *		In L4D2 some maps do not allow bosses to be spawned at all.
 *		This is known as Prohibiting Bosses. 
 *
 *		The way this is controlled, for example, is that maps have a script key called
 *		"ProhibitBosses" -- if the value is 1, no bosses are allowed on that map.
 *
 *		If the value is 0 then bosses will be allowed and subject to normal rules.
 *	
 *		This module simply force overrides the script values preventing 'Bosses'
 *		by means of detouring/overwriting or blocking their function calls.
 */

#define MODULE_NAME "UnprohibitBosses"

static const String:GAMECONFIG_FILE[]		= "left4downtown.l4d2";
static const String:GAMECONFIG_KEY[]		= "CDirector_GetScriptValueInt";
static const String:PROHIBIT_BOSSES[]		= "ProhibitBosses";
static const String:DISALLOW_THREAT[]		= "DisallowThreatType";

static const 		UNPROHIBIT_VALUE 		= 0;	// l4d2 checks if script key is non-0 to prohibit bosses

static Handle:cvarUnProhibitBosses 			= INVALID_HANDLE;
static				unprohibitBosses		= 1;

UnprohibitBosses_OnModuleLoaded()
{
	new Handle:conf = LoadGameConfigFile(GAMECONFIG_FILE);
	if(conf == INVALID_HANDLE) 
	{
		ThrowError("Could not load gamedata/%s.txt", GAMECONFIG_FILE);
	}
	
	Debug_SearchForFunction(conf, GAMECONFIG_KEY);

	cvarUnProhibitBosses = CreateConVar("srs_bosses_unprohibit", "1", "Allow tanks to spawn on maps that normally prohibit it", SRS_CVAR_DEFAULT_FLAGS);
	HookConVarChange(cvarUnProhibitBosses, _UB_ConvarChanged);
	HookConVarChange(GetGameModeHandle(), _UB_ConvarChanged);
}

public _UB_ConvarChanged(Handle:convar, const String:oldValue[], const String:newValue[])
{
	unprohibitBosses = (GetConVarBool(cvarUnProhibitBosses));
}

public Action:L4D_OnGetScriptValueInt(const String:key[], &retVal)
{
	//Debug_PrintSpam("OnGetScriptValueInt(key=\"%s\",retVal=%d)", key, retVal); 
	
	if(unprohibitBosses
	&& IsAllowedGameMode()
	&& StrEqual(key, PROHIBIT_BOSSES))
	{
		Debug_PrintSpam("Overriding OnGetScriptValueInt(ProhibitBosses)...");
		retVal = UNPROHIBIT_VALUE; //do not prohibit bosses please
		return Plugin_Handled; // return the new overridden value
	}
	
	if(unprohibitBosses
	&& IsAllowedGameMode()
	&& StrEqual(key, DISALLOW_THREAT))
	{
		Debug_PrintSpam("Overriding OnGetScriptValueInt(DisallowThreatType)...");
		retVal = UNPROHIBIT_VALUE; // Stop disallowing threat types!
		return Plugin_Handled;
	}
	
	return Plugin_Continue;
}

public Action:L4D_OnGetMissionVSBossSpawning(&Float:spawn_pos_min, &Float:spawn_pos_max, &Float:tank_chance, &Float:witch_chance)
{
	if(unprohibitBosses
	&& IsAllowedGameMode())
	{
		return Plugin_Handled; // by blocking the keyvalue function we enforce the global convar setting
	}
	
	return Plugin_Continue;
}

#undef MODULE_NAME

